﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

namespace Kiosk
{
    /// <summary>
    /// Interaction logic for KioskLogin.xaml
    /// </summary>
    public partial class KioskLogin : Window
    {
        [DllImport("user32.dll")]
        static extern bool HideCaret(IntPtr hWnd); //for caret hiding in makeshift password box
        OnScreenKeyboard theKeyboard = new OnScreenKeyboard();
        System.Windows.Forms.MaskedTextBox txtPassword;

        public KioskLogin()
        {
            InitializeComponent();

            MainGrid.Children.Add(theKeyboard);
            Grid.SetRow(theKeyboard, 1);
            Grid.SetColumn(theKeyboard, 0);
            theKeyboard.VerticalAlignment = VerticalAlignment.Top;
        }

        /// <summary>
        /// This method is called when the login button is clicked. It checks to see if the 
        /// username and password fields have text. If they do it then checks for SQL injection.
        /// If it passes all of this it will then check the credentials against the database.
        /// If the credentials are correct, then the user is logged in.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLogin_Click(object sender, RoutedEventArgs e)
        {
            sGlobals.currentUsername = txtUsername.Text;

            //Check for SQL injection
            if (!Regex.IsMatch(sGlobals.currentUsername, @"^[a-zA-Z0-9/s]{1,40}$"))
            {
                txtErrorMessage.Text = "The USERNAME or PASSWORD entered is incorrect";
            }
            //Check for an empty username or password 
            else if (sGlobals.currentUsername == null || sGlobals.currentUsername == String.Empty)
            {
                txtErrorMessage.Text = "The USERNAME can not be blank.";
            }
            else if (txtPassword.Text == String.Empty || txtPassword.Text == null)
            {
                txtErrorMessage.Text = "The PASSWORD can not be blank";
            }
            //Check the credentials against the database
            else
            {
                char permission = ' ';
                if (sGlobals.isValidPassword(sGlobals.currentUsername, txtPassword.Text, ref permission))
                {
                    //Insert into a login event into the database
                    string logSQL = "INSERT INTO lgd_user_action (action_performed_user, action_id, action_datetime, " +
                    "session_time_minutes) VALUES((SELECT user_id FROM users WHERE username = '" + sGlobals.currentUsername + "'), 'S', NOW(), 15)";

                    //Check to see if the user is an Administrator
                    if (permission == 'A')
                    {
                        Application.Current.Shutdown(0);
                    }
                    else
                    {
                        int rowsAffected = sGlobals.dbWrapper.ExecuteNonQuery(logSQL);
                        if (rowsAffected > 0)
                        {
                            //set the login time
                            sGlobals.loginTime = DateTime.Now;

                            //get the login action id so we can update the session time later
                            string logActQuery = "SELECT log_action_id FROM lgd_user_action WHERE action_performed_user = " +
                                "(SELECT user_id FROM users WHERE username = '" + sGlobals.currentUsername + "') ORDER BY log_action_id DESC LIMIT 1";
                            sGlobals.loginActionId = Convert.ToInt32(sGlobals.dbWrapper.ExecuteScalarSQL(logActQuery));
                            //set the hasLogout to false because a student is logged in.

                            //set the hasLogout so the Autologout timer will start
                            sGlobals.hasLogout = false;

                            //set the autotimeout warning and autotimeout logout times to the database settings variables. 
                            //These values are multiplied by 60 to convert the database values to minutes.
                            string autoWarnQuery = "SELECT setting_value FROM settings WHERE setting_name = 'WARNING TIMEOUT'";
                            string autoLogoutQuery = "SELECT setting_value FROM settings WHERE setting_name = 'LOGOUT TIMEOUT'";
                            sGlobals.autoWarning = (Convert.ToInt32(sGlobals.dbWrapper.ExecuteScalarSQL(autoWarnQuery)));
                            sGlobals.autoLogout = (Convert.ToInt32(sGlobals.dbWrapper.ExecuteScalarSQL(autoLogoutQuery)));
                            sGlobals.createSmtpClient();
                            sGlobals.focusedAreasOfStudy.Show();
                            this.Hide();
                        }
                        else
                        {
                            txtErrorMessage.Text = "There was a problem logging into the system. Please try again after a few minutes.\r\nIf there is still a problem please contact your system administrator";
                        }
                    }
                }
                else
                {
                    txtErrorMessage.Text = "The USERNAME or PASSWORD is not valid";
                }
            }
           
        }

        /// <summary>
        /// This mehtod clears the password and username fields. It also clears out any error messages
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            txtUsername.Clear();
            txtPassword.Clear();
            txtErrorMessage.Text = "";
        }

        private void focusHandler(object sender, RoutedEventArgs e)
        {
            if (sender is TextBox) //show keyboard and bind
            {
                theKeyboard.bindToControl((TextBox)sender);
                theKeyboard.show();
            }
            else if (sender is PasswordBox) //show keyboard and bind
            {
                theKeyboard.bindToControl((TextBox)sender);
                theKeyboard.show();
            }
            else if (sender is OnScreenKeyboard) // special do nothing case...focus is getting bounced around between the keyboard and bound control
            {

            }
            else //hide keyboard (clicked button or window or something)
            {
                theKeyboard.clearControlBinding();
                theKeyboard.hide();
            }
        }

        private void windowLeftMouseButtonUp(object sender, MouseButtonEventArgs e)
        {
            theKeyboard.clearControlBinding();
            theKeyboard.hide();
            btnLogin.Focus();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            txtPassword = new System.Windows.Forms.MaskedTextBox();
            txtPassword.Dock = System.Windows.Forms.DockStyle.Fill;
            txtPassword.Font = new System.Drawing.Font("Sequoe UI", 18);
            txtPassword.PasswordChar = '*';

            //txtPassword.Click += new EventHandler(MaskedTextBox_GotFocus); //so cursor gets hidden on click
            txtPassword.GotFocus += new EventHandler(MaskedTextBox_GotFocus);
            wfHost.Child = txtPassword;
            
        }

        private void MaskedTextBox_GotFocus(object sender, EventArgs e)
        {
            HideCaret(txtPassword.Handle);
            theKeyboard.bindToControl(sender);
            theKeyboard.show();
        }
    }
}
